package com.mvc.framework.web;

import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.mvc.framework.FrameworkConstants;
import com.mvc.framework.model.BaseEntity;
import com.mvc.framework.service.PageManager;
import com.mvc.framework.util.LocaleUtils;
import com.mvc.framework.util.MessageUtils;

/**
 * Base controller for CRUD operation
 * The entrance is create、edit、save、delete、view
 * The subclass can override handelEdit、handelSave、handelDelete
 * @author pubx 2010-3-29 02:28:33
 */
public abstract class BaseController<T> {
	
	protected Class getActualArgumentType() {
		return (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	@InitBinder
	public void initBinder(WebDataBinder binder){
		//CustomDateEditor dateEditor = new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true);
		//Date transformer
		binder.registerCustomEditor(Date.class, new JdfCustomDateEditor(true));
	}
	
	/**
	 * Go into the create page
	 * @param request
	 * @param response
	 * @param t
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/create")
	public String create(HttpServletRequest request, HttpServletResponse response, T t) throws Exception {
		return handleEdit(request, response, null);
	}

	/**
	 * Go into the edit page
	 * @param request
	 * @param response
	 * @param id primary key
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/edit/{id}")
	public String edit(HttpServletRequest request, HttpServletResponse response, @PathVariable Integer id)
	        throws Exception {
		return handleEdit(request, response, id);
	}

	protected String handleEdit(HttpServletRequest request, HttpServletResponse response, Integer id) throws Exception {
		if (null != id) {
			Object entity = getEntityManager().get(id);
			request.setAttribute("entity", entity);
		}
		return getFileBasePath() + "edit" + getActualArgumentType().getSimpleName();
	}

	/**
	 * Save the submit,and return to it's edit page
	 * @param request
	 * @param modelMap
	 * @param t Entity
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/save")
	public String save(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		return handleSave(request, modelMap, t);
	}

	protected String handleSave(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		getEntityManager().save(t);
		return "redirect:edit/" + ((BaseEntity) t).getId() + getMessage("common.base.success",request);
	}

	protected String getMessage(String message) {
		return com.mvc.framework.web.MessageUtils.getMessage(message);
	}
	
	protected String getMessage(String message,HttpServletRequest request) {
		Locale locale = LocaleUtils.getLocale(request);
		return com.mvc.framework.web.MessageUtils.getMessage(MessageUtils.getMessage(message,locale));
	}
	
	/**
	 * Save the submit,and return to query page
	 * @param request
	 * @param modelMap
	 * @param t Entity
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/saveToPage")
	public String saveToPage(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		return handleSaveToPage(request, modelMap, t);
	}

	protected String handleSaveToPage(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		getEntityManager().save(t);
		return "redirect:page" + getMessage("common.base.success",request);
	}

	/**
	 * Save the submit,and return to create page
	 * @param request
	 * @param modelMap
	 * @param t Entity
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/saveToCreate")
	public String saveToCreate(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		return handleSaveToPage(request, modelMap, t);
	}

	protected String handleSaveToCreate(HttpServletRequest request, ModelMap modelMap, T t) throws Exception {
		getEntityManager().save(t);
		return "redirect:create" + getMessage("common.base.success",request);
	}

	/**
	 * Delete entity by primary key
	 * @param request
	 * @param response
	 * @param id Primary key
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/delete/{id}")
	public String delete(HttpServletRequest request, HttpServletResponse response, @PathVariable int id)
	        throws Exception {
		return handleDelete(request, response, id);
	}

	protected String handleDelete(HttpServletRequest request, HttpServletResponse response, int id) throws Exception {
		getEntityManager().delete(id);
		return "redirect:../page" + getMessage("common.base.deleted",request);
	}

	/**
	 * Go into the view page
	 * @param request
	 * @param response
	 * @param id Primary key
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/view/{id}")
	public String view(HttpServletRequest request, HttpServletResponse response, @PathVariable int id) throws Exception {
		return handleView(request, response, id);
	}

	protected String handleView(HttpServletRequest request, HttpServletResponse response, int id) throws Exception {
		request.setAttribute(FrameworkConstants.VIEW,"1");
		return handleEdit(request, response, id);
	}

	/**
	 * Return the entity manager
	 * @return
	 */
	public abstract PageManager<T> getEntityManager();

	/**
	 * Return the parent path of the JSP page
	 * @return
	 */
	public abstract String getFileBasePath();
}
